#============================================================
#    Damage Area
#============================================================
# - datetime: 2022-09-30 00:58:36
#============================================================
##通过调用 [method set_collision_condition] 和 [method set_damage_data_callback] 
##方法设置伤害回调，处理伤害内容
class_name DamageArea
extends Area2D


## 造成伤害
signal took_damage(data)


## 节点宿主，用于 [BodyArea] 获取这个数据
@export
var host : Node 
## 是否关闭碰撞
@export
var disabled : bool = false:
	set(v):
		disabled = v
		if not self.is_inside_tree():
			await self.ready
		for child in get_children():
			if child is CollisionShape2D or child is CollisionPolygon2D:
				child.set_deferred("disabled", disabled)


## 造成伤害数据，这个方法需要返回一个数据
var _damage_data_callback : Callable
##  判断造成伤害条件，这个方法需要有一个参数，接收目标节点并返回 [bool] 值
var _condition : Callable


#============================================================
#  SetGet
#============================================================
## 设置碰撞条件，这个方法需要有一个参数，接收 [BodyArea] 节点，并返回 [bool] 值用于判断是否能对其造成伤害
func set_collision_condition(callback: Callable) -> DamageArea:
	assert(not callback.is_null())
	self._condition = callback
	return self


## 设置伤害数据回调，这个方法需要返回一个数据
func set_damage_data_callback(callback: Callable) -> DamageArea:
	assert(not callback.is_null())
	_damage_data_callback = callback 
	return self


#============================================================
#  内置
#============================================================
func _ready() -> void:
	await get_tree().physics_frame
	assert(host != null, "DamageArea 没有设置 host 属性")
	self.disabled = disabled
	self.area_entered.connect(func(area):
		if area is BodyArea:
			_damage(area)
	)


#============================================================
#  自定义
#============================================================
func _damage(area: BodyArea):
	if _condition.is_null() or _condition.call(area):
		# 对目标造成伤害
		var data = _damage_data_callback.call() 
		if data is Dictionary:
			data = data.duplicate(true)
		else:
			data = {}
		to_damage(area, data)
		data['target'] = area.host
		took_damage.emit( data.duplicate() )


##  对这个身体区域造成伤害
func to_damage(area: BodyArea, data):
	area.take_damage(data)


## 重新对这个区域内的节点造成伤害
func re_damage():
	var areas = get_overlapping_areas()
	for area in areas:
		if area is BodyArea:
			_damage(area)


## 开启一次
##[br]
##[br][code]time[/code]  持续时间，到达这个时间则关闭碰撞。如果小于0，则默认开始一帧的时间
func enable_once(time: float = 0.0):
	disabled = false
	if time <= 0:
		await get_tree().process_frame
		await get_tree().process_frame
		disabled = true
	else:
		await get_tree().create_timer(time).timeout
		disabled = true

